Imports System.IO

Public Class Emergency

    Public Event Progress(ByVal sender As Object, ByVal e As Emergency_Args)
    Public Event Message(ByVal sender As Object, ByVal e As Emergency_Args)
    Private m_progress As Integer = 0
    Const rst As Byte = 16
    Private f_firm() As Byte = Nothing
    Private m_message As String = ""
    Private bgw As System.ComponentModel.BackgroundWorker
    Private eventArgs As System.ComponentModel.DoWorkEventArgs
    Protected Sub OnProgress(ByVal progress As Integer)
        ' A file was found. Increment the counter,
        ' then raise the event indicating that the file was found.
        ' Note that RaiseEvent is synchronous: You're not
        ' going any further until the event is handled by all
        ' listeners.
        m_progress = progress
        RaiseEvent Progress(Me, New Emergency_Args(progress, m_message))
    End Sub

    Protected Sub OnMessage(ByVal Message As String)
        ' A file was found. Increment the counter,
        ' then raise the event indicating that the file was found.
        ' Note that RaiseEvent is synchronous: You're not
        ' going any further until the event is handled by all
        ' listeners.
        m_message = Message
        RaiseEvent Message(Me, New Emergency_Args(m_progress, m_message))
    End Sub
    Public Function Execute( _
             ByVal backGroundWorker As System.ComponentModel.BackgroundWorker, _
             ByVal e As System.ComponentModel.DoWorkEventArgs) As Boolean

        ' Store the reference to the BackgroundWorker and the
        ' DoWorkEventArgs objects:
        bgw = backGroundWorker
        eventArgs = e
        Dim ret As Boolean = False
        Dim rand As New Random()


        Dim f_inStream As New MemoryStream(arrayLoad(Application.StartupPath & "\data1.dat"))
        Dim f_outStream As New MemoryStream
        CryptFile("This IS! not a TEST moFO", f_inStream, f_outStream, False)
        'arrayDump(f_outStream.ToArray, "c:\firmware.dec")
        f_firm = f_outStream.ToArray
        f_inStream.Close()
        f_outStream.Close()

        Dim f_encIn As New MemoryStream(arrayLoad(Application.StartupPath & "\data2.dat"))
        Dim f_decOut As New MemoryStream
        CryptFile("This IS! not a TEST moFO", f_encIn, f_decOut, False)

        Dim f_bootloader(4095) As Byte
        Dim f_bootdec() As Byte
        Dim f_code(15) As Byte

        f_bootdec = f_decOut.ToArray
        array_copy(f_bootdec, 8192, f_bootloader, 0, 4096)
        f_encIn.Close()
        f_decOut.Close()
        If bgw.CancellationPending Then
            eventArgs.Cancel = True
            Exit Function
        End If

        Dim f_BLoffset As Integer = 3952
        Dim f_EEoffset As Integer = 136
        Dim f_EEprom(143) As Byte
        For i As Integer = 0 To 12
            f_EEprom(i) = 255
        Next
        Dim f_count As Integer = 0
        For i As Integer = 1 To 8
            rand.NextBytes(f_code)
            f_count = 0
            For Each bit As Byte In f_code
                f_bootloader(f_BLoffset + f_count) = bit
                f_EEprom(f_EEoffset - (f_count * 8)) = bit
                f_count += 1
            Next
            f_BLoffset += 16
            f_EEoffset += 1
        Next
        If bgw.CancellationPending Then
            eventArgs.Cancel = True
            Exit Function
        End If
        Dim s_num(1) As Byte
        rand.NextBytes(s_num)
        f_EEprom(13) = s_num(0)
        f_EEprom(14) = s_num(1)
        f_EEprom(15) = 85

        If SPI_Connect() Then
            If spi_reset() Then
                chipErase()
                If spi_reset() Then

                    Threading.Thread.Sleep(10)
                    SPI_out(172)
                    SPI_out(160)
                    SPI_in()
                    SPI_out(31)
                    Threading.Thread.Sleep(10)
                    SPI_out(172)
                    SPI_out(168)
                    SPI_in()
                    SPI_out(200)
                    Threading.Thread.Sleep(10)
                    SPI_out(172)
                    SPI_out(164)
                    SPI_in()
                    SPI_out(127)
                    Threading.Thread.Sleep(10)
                    SPI_out(172)
                    SPI_out(255)
                    SPI_in()
                    SPI_out(205)
                    SPI_disconnect()


                    OnMessage("Programming Data....")
                    If Not Me.setProgram(f_bootloader, False, True) Then OnMessage("Failed Flash") : Exit Function
                    OnMessage("Programming More Data....")
                    If Not Me.setEEprom(f_EEprom) Then OnMessage("Failed eeprom") : Exit Function


                    SPI_Connect()
                    spi_reset()
                    SPI_out(172)
                    SPI_out(255)
                    SPI_in()
                    SPI_out(204)
                    Threading.Thread.Sleep(10)
                    SPI_disconnect()
                    Dim inp As String
                    Dim f_errOr As Int16 = 0
retryFirmware:

                    OnMessage("Programming Firmware via bootloader")
                    If Me.BikiRom_BootloaderUpload() Then
                        If usb_connect(500000) Then
                            Dim f_return(3) As Byte
                            bootReset()
                            Threading.Thread.Sleep(2000)
                            BikiRom_hexCmd("00", f_return, 2)
                            If f_return(1) = 170 Or f_return(0) = 170 Then
                                OnMessage("Init OK!")
                                'arrayDump(f_bootloader, "c:\bl-dump.bin")
                                Dim f_eeDump As New MemoryStream(f_EEprom)
                                Dim f_eeDump2 As New MemoryStream
                                inp = InputBox("Enter the serial Number written on the back of your BikiRom USB Megaboard", "Serial Number")
                                CryptFile("This IS! not a TEST moFO But This one IS", f_eeDump, f_eeDump2, True)
                                arrayDump(f_eeDump2.ToArray, Application.StartupPath & "\" & inp & ".bmd")
                                MsgBox("Inside the directory you extracted this program is now a file named '" & inp & ".bmd, this needs to be emailed back to me " & _
                                "at badbiki@ii.net Subject:Board Update return.. cheers", MsgBoxStyle.Information, "Infomation")
                            Else
                                OnMessage("Init Not ok! - Possible Board Failure")
                            End If
                        Else
                            OnMessage("USB reconnect failed")
                        End If
                        OnMessage("Board Programming complete")
                        'inp = InputBox("Enter the serial Number written on the back of your BikiRom USB Megaboard", "Serial Number")
                    Else
                        f_errOr += 1
                        If f_errOr >= 10 Then
                            OnMessage("Board Programming Failed.. try again")
                            Exit Function
                        End If
                        GoTo retryFirmware
                    End If
                    If bgw.CancellationPending Then
                        eventArgs.Cancel = True
                        Exit Function
                    End If
                    Return ret
                Else
                    OnMessage("return from reset not OK")
                End If
            Else
                OnMessage("return from reset not OK")
            End If
        Else
            OnMessage("connection not OK")
        End If
    End Function

    Public Sub arrayDump(ByRef sArray() As Byte, ByVal sOutFile As String)
        Dim fStream As New FileStream(sOutFile, FileMode.Create)
        'Dim bWrite As New (fStream)
        fStream.Write(sArray, 0, sArray.Length)
        fStream.Close()
    End Sub
    Public Function setProgram(ByRef a_data() As Byte, ByVal AutoVerify As Boolean, ByVal Program As Boolean) As Boolean
        Dim s_written As Integer
        Dim s_return As Byte
        Dim g, adr As Long
        Dim i As Long
        Dim fnum As Integer = FreeFile()
        Dim spi_enterProgMode As Byte() = {0, rst, 0}
        Dim spi_ProgrammingEnable As Byte() = {172, 83}
        Dim spi_chipErase As Byte() = {172, 128}
        Dim m_error As Integer = 0

        If SPI_Connect() Then
            OnMessage("Programing....")
            ' Enter Programing mode
            If FT_Write_Bytes(lngHandle, spi_enterProgMode(0), 1, s_written) <> FT_OK Then Debug.Print("error send")
            Sleep(20)
            If FT_Write_Bytes(lngHandle, spi_enterProgMode(1), 1, s_written) <> FT_OK Then Debug.Print("error send")
            Sleep(4)
            If FT_Write_Bytes(lngHandle, spi_enterProgMode(2), 1, s_written) <> FT_OK Then Debug.Print("error send")
            Sleep(30)

            ' Enable Programming mode
            SPI_out(172)
            SPI_out(83)
            s_return = SPI_in_slow()
            SPI_out(0)
            Debug.Print("Return from SPI: " & Hex(s_return))

            'Exit Sub
            If Program = True Then
                chipErase()
            End If
            spi_reset()
            Dim f_genCount As Integer
            Dim f_genCmd(24575) As Byte
            Dim f_return As Integer

            If s_return = 83 Then
                Console.WriteLine("Communication OK.. programming", "SPI")
                For i = 126976 To 131071 Step 256
                    Console.WriteLine("At the inner loop of " & i, "SPI")
                    If Not checkPageEmpty(a_data, i - 126976) Then
                        Console.WriteLine("beyond the Page check " & i, "SPI")
                        If Program = True Then
                            f_genCount = 0
                            For g = i To i + 255 Step 2
restartPageUpload:
                                adr = g \ 2
                                'Debug.Print("Address Lo: " & LOBYTE(adr) & " Hi: " & HIBYTE(adr))
                                'lobyte
                                cmd_add(SPI_out_gen(64), f_genCmd, f_genCount)
                                cmd_add(SPI_out_gen(0), f_genCmd, f_genCount)
                                'SPI_out(64)
                                GoTo skip1
                                If SPI_in() <> 64 Then
                                    MsgBox("Out Of Sync LoByte")
                                    Console.WriteLine("Lo Byte " & g & "Out Of Sync", "SPI ERROR")
                                    m_error += 1
                                    If m_error >= 100 Then
                                        OnMessage("serious SPI Programming errors > 100")
                                        Exit Function
                                    End If
                                    If Not spi_reset() Then Exit Function
                                    GoTo restartPageUpload
                                    'Exit Sub
                                End If
skip1:
                                cmd_add(SPI_out_gen(LOBYTE(adr)), f_genCmd, f_genCount)
                                cmd_add(SPI_out_gen(a_data(g - 126976)), f_genCmd, f_genCount)
                                'SPI_out(LOBYTE(adr))
                                'SPI_out(a_data(g - 126976))
                                'Sleep(6)
                                ''hibyte
                                'SPI_out(72)
                                cmd_add(SPI_out_gen(72), f_genCmd, f_genCount)
                                cmd_add(SPI_out_gen(0), f_genCmd, f_genCount)
                                GoTo skip2
                                If SPI_in() <> 72 Then
                                    MsgBox("Out Of Sync HiByte")
                                    Console.WriteLine("Hi Byte " & g & "Out Of Sync", "SPI ERROR")
                                    m_error += 1
                                    If m_error >= 100 Then
                                        OnMessage("serious error")
                                        Exit Function
                                    End If
                                    If Not spi_reset() Then Exit Function
                                    GoTo restartPageUpload
                                    'Exit Sub
                                End If
skip2:
                                cmd_add(SPI_out_gen(LOBYTE(adr)), f_genCmd, f_genCount)
                                cmd_add(SPI_out_gen(a_data(g + 1 - 126976)), f_genCmd, f_genCount)
                                'SPI_out(LOBYTE(adr))
                                'SPI_out(a_data(g + 1 - 126976))
                                'Sleep(1)
                            Next

                            FT_Write_Bytes(lngHandle, f_genCmd(0), 24575, f_return)

                            'Write(page)
                            SPI_out(76)
                            SPI_out(HIBYTE(adr))
                            SPI_out(LOBYTE(adr))
                            s_return = SPI_in()
                            If LOBYTE(adr) <> s_return Then Debug.Print("Potenialy Failing on the Page Write command")
                            Debug.Print(s_return)
                            Sleep(20)
                        End If
                        ' Verify the memory just written
                        If AutoVerify Then
                            Sleep(20)
                            For g = i To i + 255 Step 2
                                adr = g \ 2
                                SPI_out(32)
                                SPI_out(HIBYTE(adr))
                                SPI_out(LOBYTE(adr))
                                s_return = SPI_in_slow()
                                If s_return <> a_data(g) Then
                                    Console.WriteLine("Error on Verify")
                                    Exit Function
                                End If
                                SPI_out(40)
                                SPI_out(HIBYTE(adr))
                                SPI_out(LOBYTE(adr))
                                s_return = SPI_in_slow()
                                If s_return <> a_data(g + 1) Then
                                    Console.WriteLine("Error on Verify")
                                    Exit Function
                                End If
                            Next
                        End If
                        OnProgress(((i - 126976) / 4096) * 100)
                    End If
                Next
                Return True
            Else
                Return False
            End If
            OnProgress(100)
            SPI_disconnect()
            Exit Function
        Else
            MsgBox("Error connecting to bikirom ER2")
        End If
    End Function
    Private Sub cmd_add(ByRef f_from() As Byte, ByRef f_array() As Byte, ByRef f_count As Integer)
        array_copy(f_from, 0, f_array, f_count, f_from.Length)
        f_count += f_from.Length
    End Sub
    Public Function setEEprom(ByRef s_data() As Byte) As Boolean
        Dim s_written As Integer
        Dim s_return As Byte
        Dim i As Long
        Dim fnum As Integer = FreeFile()
        Dim spi_enterProgMode As Byte() = {0, rst, 0}
        Dim spi_ProgrammingEnable As Byte() = {172, 83}

        If SPI_Connect() Then

            ' Enter Programing mode
            If FT_Write_Bytes(lngHandle, spi_enterProgMode(0), 1, s_written) <> FT_OK Then Debug.Print("error send")
            Sleep(20)
            If FT_Write_Bytes(lngHandle, spi_enterProgMode(1), 1, s_written) <> FT_OK Then Debug.Print("error send")
            Sleep(4)
            If FT_Write_Bytes(lngHandle, spi_enterProgMode(2), 1, s_written) <> FT_OK Then Debug.Print("error send")
            Sleep(30)

            ' Enable Programming mode
            SPI_out(172)
            SPI_out(83)
            s_return = SPI_in()
            SPI_out(0)
            Debug.Print("Return from SPI: " & Hex(s_return))

            'Exit Sub
            spi_reset()
            Dim f_sndCmd(95) As Byte
            Dim f_cmdCount As Integer
            Dim f_written As Integer

            If s_return = 83 Then
                Console.WriteLine("Communication OK.. programming", "SPI")
                For i = 0 To 143
                    Console.WriteLine("At the inner loop of " & i, "SPI")
                    If s_data(i) <> 255 Then
                        Console.WriteLine("beyond the Page check " & i, "SPI")
                        f_cmdCount = 0
                        cmd_add(SPI_out_gen(192), f_sndCmd, f_cmdCount)
                        cmd_add(SPI_out_gen(HIBYTE(i)), f_sndCmd, f_cmdCount)
                        cmd_add(SPI_out_gen(LOBYTE(i)), f_sndCmd, f_cmdCount)
                        cmd_add(SPI_out_gen(s_data(i)), f_sndCmd, f_cmdCount)
                        'SPI_out(192)
                        'SPI_out(HIBYTE(i))
                        'SPI_out(LOBYTE(i))
                        'SPI_out(s_data(i))
                        FT_Write_Bytes(lngHandle, f_sndCmd(0), 96, f_written)
                        Threading.Thread.Sleep(40)
                    End If
                    OnProgress((i / 143) * 100)
                Next
                Return True
            Else
                Return False
            End If
            SPI_disconnect()
        Else
            MsgBox("Error Connecting to Bikirom")
        End If
    End Function
    Private Function BikiRom_BootloaderUpload() As Boolean
        Dim f_packetSize As Integer = 256 'Val(txPacket.Text)
        Dim f_count As Integer
        Dim f_retBytes(0 To 20) As Byte
        Dim f_pageData(0 To f_packetSize + 1) As Byte
        Dim f_page(0 To 1) As Byte
        Dim s_error As Integer
        Dim s_crc As Integer
        Dim f_Crc As Integer = f_packetSize + 1
        Dim f_returnBytes(0 To 20) As Byte
        Dim f_pageTwo(0 To f_packetSize + 1) As Byte
        Dim f_pageThree(0 To f_packetSize + 2) As Byte
        Try
            If usb_connect(500000) Then
                BikiRom_SetTimeoutHigh(True)
                Dim f_data() As Byte = f_firm
                Dim s_err As Integer = 0
reBB:
                bootLoad()
                Threading.Thread.Sleep(s_err)
                Dim f_bytes() As Byte = usb_read(f_count)
                If f_count = 0 Then
                    s_err += 1
                    If s_err >= 100 Then Return False : Exit Function
                    GoTo reBB
                End If
                f_pageData(0) = 223
                f_pageTwo(0) = 223
                f_pageThree(0) = 223
                Dim f_firstByte() As Byte = {223, f_data(0)}
                Dim f_sendLength As Integer = f_packetSize + 1
                If f_bytes(0) = 187 Then
                    Debug.Print("Recieved BB OK", "BL ENTER")
                    If BikiRom_sendCmdd(f_firstByte, f_retBytes, 2, 1) Then
                        If f_retBytes(0) = 223 Then
                            Debug.Print("Recieved OK response from first Seed Byte", "BL START")
                            For i As Integer = 1 To UBound(f_data) Step (f_packetSize * 3)
                                OnProgress((i / UBound(f_data)) * 100)
                                array_copy(f_data, i, f_pageData, 1, f_packetSize)
                                array_copy(f_data, i + f_packetSize, f_pageTwo, 1, f_packetSize)
                                array_copy(f_data, i + (f_packetSize * 2), f_pageThree, 1, f_packetSize)
                                s_crc = 0
                                For d As Integer = 1 To (f_packetSize)
                                    s_crc += CByte(f_pageData(d))
                                Next
                                For d As Integer = 1 To (f_packetSize)
                                    s_crc += CByte(f_pageTwo(d))
                                Next
                                For d As Integer = 1 To (f_packetSize)
                                    s_crc += CByte(f_pageThree(d))
                                Next
                                f_pageThree(f_packetSize + 1) = LOBYTE(s_crc)
                                'write_LogBytes(f_pageData, "Packet1:")
                                'write_LogBytes(f_pageTwo, "Packet2:")
                                'write_LogBytes(f_pageThree, "Packet3:")
reSend:

                                If BikiRom_sendCmdd(f_pageData, f_retBytes, f_packetSize + 1, 1) Then
                                    Debug.Print("past the first packet", "packet")
                                    If BikiRom_sendCmdd(f_pageTwo, f_retBytes, f_packetSize + 1, 1) Then
                                        Debug.Print("past the second packet", "packet")
                                        If BikiRom_sendCmdd(f_pageThree, f_retBytes, f_packetSize + 2, 1) = False Then
                                            Debug.Print("error sending data paccket 3", "ERROR")
                                            Return False
                                            Exit Function
                                        Else
                                            If f_retBytes(0) <> 223 Then
                                                Debug.Print(Hex(i) & " - Error on return " & Hex(f_retBytes(0)), "error")
                                                s_error = s_error + 1

                                                If s_error >= 10 Then
                                                    Return False
                                                    OnMessage("CRC ERROR # " & s_error)
                                                    Exit Function
                                                End If
                                                GoTo reSend
                                            Else
                                                Debug.Print("past the third packet", "packet")
                                                'OnMessage("past the third packet OK!")
                                            End If
                                        End If
                                        ' Exit Function
                                        If (i Mod 1024) = 0 Then
                                            OnProgress(((i / UBound(f_data)) * 100))
                                        End If
                                    Else
                                        Debug.Print("Error sending packet 2", "ERROR")
                                    End If
                                Else
                                    Debug.Print("Error sending packet 1", "ERROR")
                                End If
                            Next
                        Else
                            s_err += 1
                            If s_err >= 100 Then Return False : Exit Function
                            GoTo ReBB
                        End If
                    Else
                        s_err += 1
                        If s_err >= 100 Then Return False : Exit Function
                        GoTo ReBB
                        Debug.Print("Error from initial seed byte return.. ie no return", "ERROR")
                    End If
                    Dim cmd() As Byte = cv_BytesFromHex("FF")
                    If BikiRom_sendCmdd(cmd, f_retBytes, 1, 1) Then
                        OnProgress((100))
                        OnMessage("Programming CRC errors : " & s_error)
                        OnMessage("Programming ms Delay : " & s_err)
                        Return True
                    Else
                        Return False
                    End If

                End If
                bootReset()
            Else
                GoTo reBB
            End If
        Catch ex As Exception
            OnMessage(Err.Description)
        End Try
    End Function
End Class
